Function: c-forward-<>-arglist-recur

c-forward-<>-arglist-recur is a byte-compiled function defined in cc-engine.el.gz.

Signature

(c-forward-<>-arglist-recur ALL-TYPES)

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/cc-engine.el.gz
(defun c-forward-<>-arglist-recur (all-types)
  ;; Recursive part of `c-forward-<>-arglist'.
  ;;
  ;; This function might do hidden buffer changes.
  (let ((start (point)) res pos
	;; Cover this so that any recorded found type ranges are
	;; automatically lost if it turns out to not be an angle
	;; bracket arglist.  It's propagated through the return value
	;; on successful completion.
	(c-record-found-types c-record-found-types)
	(syntax-table-prop-on-< (c-get-char-property (point) 'syntax-table))
	;; List that collects the positions after the argument
	;; separating ',' in the arglist.
	arg-start-pos)
    ;; If the '<' has paren open syntax then we've marked it as an angle
    ;; bracket arglist before, so skip to the end.
    (if (and (not c-parse-and-markup-<>-arglists)
	     syntax-table-prop-on-<)

	(progn
	  (forward-char)
	  (if (and (c-go-up-list-forward)
		   (eq (char-before) ?>))
	      t
	    ;; Got unmatched paren angle brackets.  We don't clear the paren
	    ;; syntax properties and retry, on the basis that it's very
	    ;; unlikely that paren angle brackets become operators by code
	    ;; manipulation.  It's far more likely that it doesn't match due
	    ;; to narrowing or some temporary change.
	    (goto-char start)
	    nil))

      (forward-char) ; Forward over the opening '<'.

      (unless (and (looking-at c-<-op-cont-regexp)
		   (not (looking-at c-<-pseudo-digraph-cont-regexp)))
	;; go forward one non-alphanumeric character (group) per iteration of
	;; this loop.
	(while (and
		(progn
		  (c-forward-syntactic-ws)
		  (when (or (and c-record-type-identifiers all-types)
			    (not (equal c-inside-<>-type-key
					(concat
					 "\\(" regexp-unmatchable "\\)"))))
		    (c-forward-syntactic-ws)
		    (cond
		     ((eq (char-after) ??)
		      (forward-char))
		     ((and (looking-at c-identifier-start)
			   (not (looking-at c-keywords-regexp)))
		      (if (or (and all-types c-record-type-identifiers)
			      (c-major-mode-is 'java-mode))
			  ;; All encountered identifiers are types, so set the
			  ;; promote flag and parse the type.
			  (let ((c-promote-possible-types t)
				(c-record-found-types t))
			    (c-forward-type))
			(c-forward-over-token-and-ws))))

		    (c-forward-syntactic-ws)

		    (when (looking-at c-inside-<>-type-key)
		      (goto-char (match-end 1))
		      (c-forward-syntactic-ws)
		      (let ((c-promote-possible-types t)
			    (c-record-found-types t))
			(c-forward-type))
		      (c-forward-syntactic-ws)))

		  (setq pos (point))	; e.g. first token inside the '<'

		  ;; Note: These regexps exploit the match order in \| so
		  ;; that "<>" is matched by "<" rather than "[^>:-]>".
		  (c-syntactic-re-search-forward
		   ;; Stop on ',', '|', '&', '+' and '-' to catch
		   ;; common binary operators that could be between
		   ;; two comparison expressions "a<b" and "c>d".
		   ;; 2016-02-11: C++11 templates can now contain arithmetic
		   ;; expressions, so template detection in C++ is now less
		   ;; robust than it was.
		   c-<>-notable-chars-re
		   nil t t))

		(cond
		 ((eq (char-before) ?>)
		  ;; Either an operator starting with '>' or the end of
		  ;; the angle bracket arglist.

		  (if (save-excursion
			(c-backward-token-2)
			(looking-at c-multichar->-op-not->>->>>-regexp))
		      (progn
			(goto-char (match-end 0))
			t)		; Continue the loop.

		    ;; The angle bracket arglist is finished.
		    (when c-parse-and-markup-<>-arglists
		      (while arg-start-pos
			(c-put-c-type-property (1- (car arg-start-pos))
					       'c-<>-arg-sep)
			(setq arg-start-pos (cdr arg-start-pos)))
		      (when (and (not syntax-table-prop-on-<)
				 (c-get-char-property (1- (point))
						      'syntax-table))
			;; Clear the now spuriously matching < of its
			;; syntax-table property.  This could happen on
			;; inserting "_cast" into "static <" with C-y.
			(save-excursion
			  (and (c-go-list-backward)
			       (eq (char-after) ?<)
			       (c-truncate-lit-pos-cache (point))
			       (c-unmark-<->-as-paren (point)))))
		      (c-mark-<-as-paren start)
		      (c-mark->-as-paren (1- (point)))
		      (c-truncate-lit-pos-cache start))
		    (setq res t)
		    nil))		; Exit the loop.

		 ((eq (char-before) ?<)
		  ;; Either an operator starting with '<' or a nested arglist.
		  (setq pos (point))
		  (let (id-start id-end subres keyword-match)
		    (cond
		     ;; The '<' begins a multi-char operator.
		     ((and (looking-at c-<-op-cont-regexp)
			   (not (looking-at c-<-pseudo-digraph-cont-regexp)))
		      (goto-char (match-end 0)))
		     ;; We're at a nested <.....>
		     ((progn
			(backward-char)	; to the '<'
			(and
			 (save-excursion
			   ;; There's always an identifier before an angle
			   ;; bracket arglist, or a keyword in `c-<>-type-kwds'
			   ;; or `c-<>-arglist-kwds'.
			   (c-backward-syntactic-ws)
			   (setq id-end (point))
			   (c-simple-skip-symbol-backward)
			   (when (or (setq keyword-match
					   (looking-at c-opt-<>-sexp-key))
				     (not (looking-at c-keywords-regexp)))
			     (setq id-start (point))))
			 (setq subres
			       (let ((c-promote-possible-types t)
				     (c-record-found-types t))
				 (c-forward-<>-arglist-recur
				  (and keyword-match
				       (c-keyword-member
					(c-keyword-sym (match-string 1))
					'c-<>-type-kwds))))))
			(or subres (goto-char pos))
			subres)
		      ;; It was an angle bracket arglist.
		      (setq c-record-found-types subres)

		      ;; Record the identifier before the template as a type
		      ;; or reference depending on whether the arglist is last
		      ;; in a qualified identifier.
		      (when (and c-record-type-identifiers
				 (not keyword-match))
			(if (and c-opt-identifier-concat-key
				 (progn
				   (c-forward-syntactic-ws)
				   (looking-at c-opt-identifier-concat-key)))
			    (c-record-ref-id (cons id-start id-end))
                        (c-record-type-id (cons id-start id-end)))))

		     ;; At a "less than" operator.
		     (t
		      ;; (forward-char) ; NO!  We've already gone over the <.
		      )))
		  t)			; carry on looping.

		 ((and
		   (eq (char-before) ?\()
		   (c-go-up-list-forward)
		   (eq (char-before) ?\))))

		 ((and (not c-restricted-<>-arglists)
		       (or (and (eq (char-before) ?&)
				(not (eq (char-after) ?&)))
			   (eq (char-before) ?,)))
		  ;; Just another argument.  Record the position.  The
		  ;; type check stuff that made us stop at it is at
		  ;; the top of the loop.
		  (setq arg-start-pos (cons (point) arg-start-pos)))

		 (t
		  ;; Got a character that can't be in an angle bracket
		  ;; arglist argument.  Abort using `throw', since
		  ;; it's useless to try to find a surrounding arglist
		  ;; if we're nested.
		  (throw 'angle-bracket-arglist-escape nil))))))
      (if res
	  (or c-record-found-types t)))))